package com.csw.encryptiontechnology.utils.mapperRSA;

import cn.hutool.core.util.ReflectUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class Sm4ServiceImpl implements Sm4Service {


    @Override
    public <T> T encrypt(Field[] declaredFields, T paramsObject) throws Exception {
        for (Field field : declaredFields) {
            //取出所有被EncryptDecryptField注解的字段
            SensitiveField sensitiveField = field.getAnnotation(SensitiveField.class);
            if (Objects.isNull(sensitiveField)) {
                continue;
            }
            field.setAccessible(true);
            Object object = field.get(paramsObject);
            //暂时只实现String类型的加密
            if (object instanceof String) {
                String value = (String) object;
                //如果映射字段值为空,并且以==结尾则跳过不进行加密
                if (StringUtils.isEmpty(value) || isBase64(value)) {
                    continue;
                }
                //加密  这里我使用自定义的AES加密工具
                field.set(paramsObject, Sm4Util.encrypt(value));
            }
        }
        return paramsObject;

    }

    @Override
    public <T> T decrypt(T result) throws Exception {
        //取出resultType的类
        Class<?> resultClass = result.getClass();
        Field[] allFields = ReflectUtil.getFields(resultClass);
        //Field[] declaredFields = resultClass.getDeclaredFields();
        for (Field field : allFields) {
            //取出所有被EncryptDecryptField注解的字段
            SensitiveField sensitiveField = field.getAnnotation(SensitiveField.class);
            if (Objects.isNull(sensitiveField)) {
                continue;
            }
            field.setAccessible(true);
            Object object = field.get(result);
            //只支持String的解密
            if (object instanceof String) {
                String value = (String) object;
                //如果映射字段值为空,并且不已==结尾则跳过不进行解密/之前加密方式不一样，所以注掉
                if (StringUtils.isBlank(value)/* || !EncryptUtil.isBase64(value)*/) {
                    continue;
                }
                //对注解的字段进行逐一解密
                field.set(result, Sm4Util.decrypt(value));
            }
        }
        return result;
    }

    /**
     * base64验证规则
     */
    private static final String BASE64_RULE = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)=?$";

    /**
     * 正则验证对象
     */
    private static final Pattern PATTERN = Pattern.compile(BASE64_RULE);


    /**
     * 判断是否为 base64加密
     *
     * @param str 参数
     * @return 结果
     */
    public static boolean isBase64(String str) {
        Matcher matcher = PATTERN.matcher(str);
        return matcher.matches();
    }

}


